#include <stdio.h>
#include <string.h>
#include "rgb.h"
#include "beep.h"
#include "rcc.h"
#include "systick.h"
#include "button.h"
#include "pccom.h"
#include "flash.h"
#include "light.h"
#include "dma.h"
#include "adc.h"
#include "i2c.h"
#include "eeprom.h"
#include "spi.h"
#include "esp8266.h"
#include "stm32f10x.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_usart.h"

// 典型的嵌入式裸程序：
// 主程序中包含一个while(1)死循环
// 循环中执行必须的代码，或者直接留空
// 嵌入式程序通常不会结束，而是上电即运行，断电才停止

// 嵌入式的核心逻辑：使用c语言代码操作寄存器
// 1. 直接操作寄存器
// GPIOA->ODR |= (1 << 5); // 将GPIOA->ODR的第五位设置为高（即1）
// GPIOA->ODR &= -(1 << 5); // 将GPIOA->ODR的第五位设置为低（即0）
// 2. ST官方提供的标准库，将一些操作封装成函数
// GPIO_SetBits(GPIOA, GPIO_Pin_5);
// GPIO_ResetBits(GPIOA, GPIO_Pin_5);
// 3. ST官方提供的新版本HAL/LL库
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

// 中断处理函数：
// 大部分外设具有xxx_GetFlagStatus()和xxx_GetITStatus()两个函数
// 它们能够获取外设当前标志位情况
// 区别：轮询模式应该使用前者
//      在中断处理函数中应该使用后者
// xxx_ClearFlag()和xxx_ClearITFlag()同理

// 使用空循环，模拟延时效果
// 缺点：不准确，且难以计算
// void delay(uint32_t mul)
// {
// 	for(int i = 10000; i > 0; i--)
// 	{
// 		for(int j = mul; j > 0; j--)
// 			;
// 	}
// }

// uint32_t isCmd = 0;
// uint8_t espCmd[16];
// uint8_t espResp[16];
// uint8_t type, num, action;

// 新增函数声明
void SendToServer(const char *data);
// void SendLightStatus(uint8_t status);
void SendTemperatureData(int temperature);
void SendVRData(uint32_t vrVoltage);

int main()
{
	// 数据初始化
	// uint8_t data[] = "hello world.\r\n";
	// uint8_t recv_data = 0;

	// 1. 外设初始化
	// RGB_init(); // RGB灯
	// BEEP_init(); // 蜂鸣器
	// myRCC_init(); // 系统时钟
	mySYSTICK_init(); // 系统滴答计时器
	BUTTON_init();	  // 按键初始化
	PCCOM_init();	  // UASRT初始化（电脑自己发送自己接收）
	// FLASH_init();
	LIGHT_init();
	myADC_Init();
	// myI2C_Init();
	// mySPI_Init();
	ESP8266_Init();

	extern uint16_t adcVal[2]; // 采样值, 实际声明在adc.c中
	// VR相关
	uint32_t VRVoltage = 0; // 计算出的实际VR电压值
	// temp相关
	uint32_t tempVoltage = 0; // 计算出的Temp通道实际电压值
	int16_t vol25 = 1430;	  // 25度时的采样值, 查F103vet6手册
	float avg_slope = 4.3;	  // 温度斜率, 查F103vet6手册
	float temp = 0;			  // 计算出的实际温度值

	// 2. 一次性工作
	// 2.1 亮灯
	// RGB_redOff();
	// 2.2 蜂鸣器
	// BEEP_off();

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);

	// 3. 循环工作
	while (1)
	{
		mySYSTICK_delayMs(1000);
		// 计算VR的电压值
		VRVoltage = (uint32_t)adcVal[0] * 3300 >> 12;
		// 计算Temp的电压值
		tempVoltage = (uint32_t)adcVal[1] * 3300 >> 12;
		// 计算Temp电压值对应的温度
		temp = (vol25 - tempVoltage) / avg_slope + 25;
		// 发送传感器数据到服务器
		SendTemperatureData(temp);
		SendVRData(VRVoltage);
	}
}

// 通过ESP8266发送数据到服务器
void SendToServer(const char *data)
{
	// 在透传模式下直接发送字符串
	while (*data)
	{
		USART_SendData(USART3, *data++);
		while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET)
			;
	}
	// 发送换行符以便服务器区分不同消息
	USART_SendData(USART3, '\r');
	while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET)
		;
	USART_SendData(USART3, '\n');
	while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET)
		;
}

// 发送温度数据
void SendTemperatureData(int temperature)
{
	char tempStr[32];
	sprintf(tempStr, " TEMP: %dC", temperature);
	SendToServer(tempStr);
}

// 发送VR电压数据
void SendVRData(uint32_t vrVoltage)
{
	char vrStr[32];
	sprintf(vrStr, " VR: %dmV", vrVoltage);
	SendToServer(vrStr);
}
